
/*
avr-gcc -DF_CPU=16000000UL -mmcu=atmega328p -o OS.out OS.c
avr-objcopy -O ihex -R .eeprom OS.out OS.hex
avrdude -b57600 -patmega328p -cstk500v1 -P/dev/ttyUSB0 -U flash:w:OS.hex

// for windows use this to push to the Meggy Jr
avrdude -b57600 -patmega328p -cstk500v1 -PCOM3 -U flash:w:OS.hex
*/

//#include <avr/io.h>
//#include "graphics.c"
//#include "sounds.c"
//#include "buttons.c"
#include "scribble.c"
#include "game.c"
#include "interrupt.c"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <stdlib.h>

char* colours[7];
uint8_t i, j;

void SetUpColours()
{
	colours[0] = "RED";
	colours[1] = "GREEN";
	colours[2] = "BLUE";
	colours[3] = "YELLOW";
	colours[4] = "PURPLE";
	colours[5] = "LIGHTBLUE";
	colours[6] = "WHITE";
}

void Setup()
{
	SetUpColours();
	VariableSetup();
	initFrameBuffer();
	EnableSounds();
	SetUpButtons();
}

void Method1()
{
	while (1)
	{
		int i, j, k;
		for (i = 0; i <= 6; i++)
		{
			for (k = 0; k < 2; k ++)
			{
				for (j = 0; j < 10; j++)
				{
					ClearScreen();
					DrawSpaceInvader1(colours[i]);
					drawFrameBuffer();
				}
				for (j = 0; j < 10; j++)
				{
					ClearScreen();
					DrawSpaceInvader2(colours[i]);
					drawFrameBuffer();
				}
			}
		}		
	}
}

uint8_t currentThread = 0;
uint8_t numThreads = 2;
uint8_t stackPointers[4];
uint8_t firstSwitch = 1;
uint8_t soundFrequency = 0;
uint8_t soundDuration = 0;
uint16_t *stack;

char *colours2[8] = {"RED","LIGHTBLUE","GREEN","BLUE","YELLOW","PINK","PURPLE","WHITE"};
   
void SpriteAnimation()
{
	uint8_t i, j;
	while (1)
	{
		for (i = 0; i < 8; i ++)
		{
			ClearScreen();
			DrawPlane(colours2[i]);
			for (j = 0; j < 10; j ++)
			{
				drawFrameBuffer();
			}
		}
		for (i = 0; i < 8; i ++)
		{
			ClearScreen();
			DrawSpaceInvader1(colours2[i]);
			for (j = 0; j < 10; j ++)
			{
				drawFrameBuffer();
			}
			DrawSpaceInvader2(colours2[i]);
			for (j = 0; j < 10; j ++)
			{
				drawFrameBuffer();
			}
		}
	}
}

static int8_t GameScreen = 0;

void RunGame(uint8_t GameScreen)
{
	ClearScreen();
	if (GameScreen == 0)
	{
		SpriteAnimation();
	}
	else if (GameScreen == 1)
	{
		SetupThreadSwapTimer();
		Game1();
	}
	else if (GameScreen == 2)
	{
		//SetupThreadSwapTimer();
		//Game2();
	}
	else if (GameScreen == 3)
	{
		Scribble();
	}
}

void DisplayGameScreen(uint8_t GameScreen)
{	
	//Draws a 0 on screen
	if (GameScreen == 0) 
	{
		DrawPixel(3,1,"RED");
		DrawPixel(4,1,"RED");
		DrawPixel(5,2,"RED");
		DrawPixel(6,3,"RED");
		DrawPixel(6,4,"RED");
		DrawPixel(5,5,"RED");
		DrawPixel(4,6,"RED");
		DrawPixel(3,6,"RED");
		DrawPixel(2,5,"RED");
		DrawPixel(1,4,"RED");
		DrawPixel(1,4,"RED");
		DrawPixel(2,3,"RED");
	}
	//Draws a 1 on screen
	if (GameScreen == 1) 
	{
		DrawPlane("BLUE");
	}
	//Draws a 2 on screen
	if (GameScreen == 2) 
	{
		DrawSpaceInvader1("WHITE");	
	}
	//Draws a 3 on screen
	if (GameScreen == 3) 
	{
		DrawPixel(2,1,"PURPLE");
		DrawPixel(3,1,"PURPLE");
		DrawPixel(4,1,"PURPLE");
		DrawPixel(5,1,"PURPLE");
		DrawPixel(2,2,"PURPLE");
		DrawPixel(3,3,"PURPLE");
		DrawPixel(4,4,"PURPLE");
		DrawPixel(3,4,"PURPLE");
		DrawPixel(2,5,"PURPLE");
		DrawPixel(2,6,"PURPLE");
		DrawPixel(3,6,"PURPLE");
		DrawPixel(4,6,"PURPLE");
		DrawPixel(5,6,"PURPLE");		
	}
}

void Menu()
{
	while(1)
	{
		cli();
		if (LeftArrowButton())
		{
			if (GameScreen == 0)
			{
				GameScreen = 4;
			}
			GameScreen = GameScreen - 1;
		}

		if (RightArrowButton())
		{
			GameScreen = (GameScreen + 1) % 4;
		}

		if (RightCircleButton()) 
		{
			RunGame(GameScreen);
		}
		EndButtons();
		sei();
		
		ClearScreen();
		DisplayGameScreen(GameScreen);
		drawFrameBuffer();
	}
}

FirstSwitch()
{
	uint8_t i;
	SPH = (uint8_t)((uint16_t)(stack + 511) >> 8);
	SPL = (uint8_t)((uint16_t)(stack + 511));
	//for (i = 0; i < 0x7FU; i ++)
	//{
	//	asm("push r0");
	//}
	firstSwitch = 0;
	sei( );
	Draw();
}

ISR(TIMER2_COMPA_vect, ISR_NAKED)
 {
	cli();
	asm("push r0");
	asm("push r1");
	asm("push r2");
	asm("push r3");
	asm("push r4");
	asm("push r5");
	asm("push r6");
	asm("push r7");
	asm("push r8");
	asm("push r9");
	asm("push r10");
	asm("push r11");
	asm("push r12");
	asm("push r13");
	asm("push r14");
	asm("push r15");
	asm("push r16");
	asm("push r17");
	asm("push r18");
	asm("push r19");
	asm("push r20");
	asm("push r21");
	asm("push r22");
	asm("push r23");
	asm("push r24");
	asm("push r25");
	asm("push r26");
	asm("push r27");
	asm("push r28");
	asm("push r29");
	asm("push r30");
	asm("push r31");
	stackPointers[2*currentThread] = SPH;
	stackPointers[2*currentThread + 1] = SPL;
	currentThread = (currentThread + 1) % numThreads;
	if (firstSwitch)
	{
		FirstSwitch();
	}
	else
	{
		SPH = stackPointers[2*currentThread];
		SPL = stackPointers[2*currentThread + 1];
		asm("pop r31");
		asm("pop r30");
		asm("pop r29");
		asm("pop r28");
		asm("pop r27");
		asm("pop r26");
		asm("pop r25");
		asm("pop r24");
		asm("pop r23");
		asm("pop r22");
		asm("pop r21");
		asm("pop r20");
		asm("pop r19");
		asm("pop r18");
		asm("pop r17");
		asm("pop r16");
		asm("pop r15");
		asm("pop r14");
		asm("pop r13");
		asm("pop r12");
		asm("pop r11");
		asm("pop r10");
		asm("pop r9");
		asm("pop r8");
		asm("pop r7");
		asm("pop r6");
		asm("pop r5");
		asm("pop r4");
		asm("pop r3");
		asm("pop r2");
		asm("pop r1");
		asm("pop r0");
	}
	reti();
}

int main()
{
	Setup();
	stack = malloc(512 * sizeof(uint8_t));
	sei( ); // Enable interrupts
	//Method1();
	Menu();
	return 0;
}
